#ifndef _EXTAPPLAUNCHER_H_
#define _EXTAPPLAUNCHER_H_

#include <wx/wx.h>
#include <wx/dynlib.h>
#include <windows.h>
#include <process.h>
 
// ============================================================================
// Headers
// ===========================================================================
#ifdef _LIBNAME_R_
	static const char* LIBNAME_R = _LIBNAME_R_;
#else
	static const char* LIBNAME_R = "ext_";
#endif

static const int CMD_TERMINATE = wxNewId();

class MyDllApp : public wxApp
{
public:
    MyDllApp();

private:
    void OnTerminate(wxThreadEvent& event);
};


// ============================================================================
// implementation MyDllApp
// ============================================================================

MyDllApp::MyDllApp()
{

    SetExitOnFrameDelete(false);

    Connect(wxEVT_IDLE, wxIdleEventHandler(MyDllApp::OnIdle));
    Connect(CMD_TERMINATE,
            wxEVT_COMMAND_THREAD,
            wxThreadEventHandler(MyDllApp::OnTerminate));
}


void MyDllApp::OnTerminate(wxThreadEvent& WXUNUSED(event))
{
    ExitMainLoop();
}


// ----------------------------------------------------------------------------
// application startup
// ----------------------------------------------------------------------------
IMPLEMENT_APP_NO_MAIN(MyDllApp)

namespace
{

wxCriticalSection gs_wxStartupCS;

HANDLE gs_wxMainThread = NULL;

unsigned wxSTDCALL MyAppLauncher(void* event)
{
    const HINSTANCE hInstance = GetModuleHandle(NULL);
		//wxDynamicLibrary::MSWGetModuleHandle(LIBNAME_R, &gs_wxMainThread);

    if ( !hInstance )
        return 0; // failed to get DLL's handle

    wxDISABLE_DEBUG_SUPPORT();

    wxInitializer wxinit;
    if ( !wxinit.IsOk() )
        return 0; // failed to init wx

    HANDLE hEvent = *(static_cast<HANDLE*>(event));
    if ( !SetEvent(hEvent) )
        return 0; // failed setting up the mutex

    // Run the app:
    wxEntry(hInstance);

    return 1;
}

}

// ----------------------------------------------------------------------------
// public DLL interface
// ----------------------------------------------------------------------------


void run_wx_gui_from_dll()
{
    wxCriticalSectionLocker lock(gs_wxStartupCS);

    if ( !gs_wxMainThread )
    {
        HANDLE hEvent = CreateEvent
                        (
                            NULL,  // default security attributes
                            FALSE, // auto-reset
                            FALSE, // initially non-signaled
                            NULL   // anonymous
                        );
        if ( !hEvent )
            return; // error

        gs_wxMainThread = (HANDLE)_beginthreadex
                                  (
                                      NULL,           // default security
                                      0,              // default stack size
                                      &MyAppLauncher,
                                      &hEvent,        // arguments
                                      0,              // create running
                                      NULL
                                  );

        if ( !gs_wxMainThread )
        {
            CloseHandle(hEvent);
            return; // error
        }

        WaitForSingleObject(hEvent, INFINITE);
        CloseHandle(hEvent);
    }
}

void wx_dll_cleanup()
{
    wxCriticalSectionLocker lock(gs_wxStartupCS);

    if ( !gs_wxMainThread )
        return;

    wxThreadEvent *event =
        new wxThreadEvent(wxEVT_COMMAND_THREAD, CMD_TERMINATE);
    wxQueueEvent(wxApp::GetInstance(), event);

    WaitForSingleObject(gs_wxMainThread, INFINITE);
    CloseHandle(gs_wxMainThread);
    gs_wxMainThread = NULL;
}

#endif